package cn.iniche;

import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresPermission;
import androidx.core.content.ContextCompat;
import androidx.preference.MultiSelectListPreference;
import androidx.preference.PreferenceManager;

import com.just.agentweb.AgentWebConfig;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.microedition.util.ContextHolder;

import cn.iniche.utils.EncryptUtils;
import cn.iniche.utils.SingletonHelper;
import cn.iniche.utils.StringUtils;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import ru.playsoftware.j2meloader.R;
import ru.playsoftware.j2meloader.util.FileUtils;

import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static ru.playsoftware.j2meloader.util.Constants.PREF_SCREENSHOT;


public final class ScreenshotHelper {

    private static final String UPLOAD_URL = "https://iniche.cn/screens";
    private static Set<String> sAutoUploadConfig;

    public static void setAutoUploadConfig(@Nullable Set<String> values) {
        if (values == null) {
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(ContextHolder.getAppContext());
            values = preferences.getStringSet(PREF_SCREENSHOT, null);
            if (values == null) {
                values = new HashSet<>(2);
                Collections.addAll(values, "1", "2");
                preferences.edit().putStringSet(PREF_SCREENSHOT, values).apply();
            }
        }
        sAutoUploadConfig = values;
    }

    public static void initPreference(@NonNull MultiSelectListPreference preference) {
        applySummaryWithConfig(preference, preference.getValues());
        //noinspection unchecked
        preference.setOnPreferenceChangeListener(
                (preference1, newValue) ->
                        applySummaryWithConfig((MultiSelectListPreference) preference1, (Set<String>) newValue)
        );
    }


    public static String getGameMd5(String gameDir) {
        File md5File = new File(gameDir, "md5");
        if (md5File.exists() && md5File.isFile()) {
            return FileUtils.getText(md5File.getAbsolutePath());
        }

        File resJar = new File(gameDir, "res.jar");
        if (resJar.exists() && resJar.isFile()) {
            String md5 = EncryptUtils.getFileMd5(resJar);
            FileUtils.writeText(md5File.getAbsolutePath(), md5);
            return md5;
        }

        return "";
    }


    public static void uploadScreenshot(final @NonNull Bitmap src, final int width, final int height, @NonNull final String gameMd5) {
        if (!allowUpload() && !TextUtils.isEmpty(gameMd5)) {
            return;
        }

        final Runnable uploader = () -> {

            final String cookie = AgentWebConfig.getCookiesByUrl(UPLOAD_URL);
            final Bitmap bitmap = compressBitmap(src, width, height);
            byte[] bytes = new byte[0];
            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
                bytes = bos.toByteArray();
                bos.close();
            } catch (IOException ignored) {

            }
            MultipartBody.Builder builder = new MultipartBody.Builder();
            builder.setType(MultipartBody.FORM);
            builder.addFormDataPart("md5hash", gameMd5);
            builder.addFormDataPart("screen", gameMd5 + ".png",
                    RequestBody.create(MediaType.parse("image/png"), bytes));

            Request request = new Request.Builder()
                    .url(UPLOAD_URL)
                    .header("User-Agent", StringUtils.USER_AGENT)
                    .header("Cookie", cookie)
                    .header("Ajax", String.valueOf(true))
                    .post(builder.build())
                    .build();
            String message;
            try {
                Response response = SingletonHelper.getOkHttpClient().newCall(request).execute();
                if (response.isSuccessful()) {
                    String string = response.body().string();
                    try {
                        message = new JSONObject(string).getString("message");
                    } catch (JSONException e) {
                        message = string;
                    }
                } else {
                    message = String.format("截图上传失败[%s], %s", String.valueOf(response.code()), "请检查登录状态");
                }
            } catch (IOException e) {
                e.printStackTrace();
                message = String.format("截图上传失败, 请检查网络状态 [%s]", e.getMessage());
            }
            toastMessage(message);
        };

        new Thread(uploader).start();
    }


    private static void toastMessage(String message) {
        new Handler(Looper.getMainLooper()).post(
                () -> Toast.makeText(ContextHolder.getAppContext(), String.valueOf(message), Toast.LENGTH_LONG).show()
        );
    }


    private static Bitmap compressBitmap(Bitmap src, float width, float height) {
        try {
            int srcWidth = src.getWidth();
            int srcHeight = src.getHeight();
            float scale;
            if (srcWidth >= srcHeight) {
                if (width >= srcWidth) return src;
                scale = width / srcWidth;
            } else {
                if (height >= srcHeight) return src;
                scale = height / srcHeight;
            }
            Matrix matrix = new Matrix();
            matrix.setScale(scale, scale);
            Bitmap bitmap = Bitmap.createBitmap(src, 0, 0, srcWidth, srcHeight, matrix, true);
            src.recycle();
            return bitmap;
        } catch (Exception e) {
            return src;
        }
    }


    private static boolean allowUpload() {
        if (sAutoUploadConfig == null || sAutoUploadConfig.isEmpty() || !sAutoUploadConfig.contains("1")) {
            return false;
        }
        return isConnected(!sAutoUploadConfig.contains("2"));
    }


    private static boolean applySummaryWithConfig(@NonNull MultiSelectListPreference preference, @Nullable Set<String> values) {
        if (values == null || values.isEmpty() || !values.contains("1")) {
            preference.setSummary(R.string.screenshots_not_auto_upload);
            preference.setValues(Collections.emptySet());
            setAutoUploadConfig(Collections.emptySet());
            return false;
        }
        if (values.contains("2")) {
            preference.setSummary(R.string.screenshots_auto_upload);
        } else {
            preference.setSummary(R.string.screenshots_auto_upload_with_wifi);
        }
        setAutoUploadConfig(values);
        return true;
    }


    @RequiresPermission(ACCESS_NETWORK_STATE)
    private static boolean isConnected(boolean onlyWifi) {
        ConnectivityManager cm = ContextCompat.getSystemService(ContextHolder.getAppContext(), ConnectivityManager.class);
        NetworkInfo info = cm == null ? null : cm.getActiveNetworkInfo();
        if (info == null) return false;
        if (onlyWifi && info.getType() != ConnectivityManager.TYPE_WIFI) return false;
        return info.isConnected();
    }

}
